package net.wangds.jdbc.comp.jdbc;

import net.wangds.utils.JsonUtils;
import net.wangds.log.helper.LogHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class JdbcComp {

    @Autowired
    JdbcTemplate jdbc;

    private String procKey(String key){
        if(key.contains("_")){
            StringBuffer sb = new StringBuffer();
            int len = key.length();
            boolean upcase = false;
            for(int i=0;i<len;i++){
               char c = key.charAt(i);
               if(upcase){
                if(c=='_'){
                    continue;
                }
                sb.append(Character.toUpperCase(c));
                upcase = false;
               }else{
                   if(c=='_'){
                       upcase=true;
                       continue;
                   }else{
                       sb.append(c);
                   }
               }
            }
            return sb.toString();
        }else{
            char c0 = key.charAt(0);
            if(Character.isUpperCase(c0)){
                key = Character.toLowerCase(c0) + key.substring(1);
            }
            return key;
        }
    }

    private Map<String, Object> proceMapKey(Map<String, Object> inMap){
        if(inMap==null){
            return new HashMap<>();
        }

        Map<String, Object> outMap = new HashMap<>(inMap.size());

        inMap.forEach((k,v)->{
            // LogHelper.debug("key:"+k+",value:"+v+",  pk:"+procKey(k));
            outMap.put(procKey(k), v);
        });

        return outMap;
    }

    public <T> List<T> executeQuery(String sql, Object[] params, Class<T> rsType){
        LogHelper.debug(()->sql+",params:["+JsonUtils.toJsonStr(params)+"]");
        return jdbc.queryForList(sql, params==null?new Object[0]:params)
                .stream()
                .map(m->proceMapKey(m))
                .map(m->JsonUtils.fromJsonStr(JsonUtils.toJsonStr(m), rsType))
                .collect(ArrayList::new, (acc, t)->acc.add(t), ArrayList::addAll);

    }


    public <T> Page<T> executeQuery(String sql, Object[] params, Pageable page, Class<T> rsType){

        String countSql = "select count(*) from ("+sql+") _cnt_sql";
        LogHelper.debug(()->"count sql:"+countSql);
        Long cnt =jdbc.queryForObject(countSql, params, Long.class);

        if(cnt==null){
            cnt = 0L;
        }

        String pageSql = "select * from ("+sql+") _pg_sql limit "+page.getOffset()+","+page.getPageSize();
        LogHelper.debug(()->"page sql:"+pageSql);
        return new PageImpl<>(executeQuery(pageSql, params, rsType), page, cnt);
    }

    public long executeQueryAsLong(String sql, Object[] params){
        return jdbc.queryForObject(sql, params, Long.class);
    }

    public int executeUpdate(String sql) {
        return jdbc.update(sql);
    }


    public int executeUpdate(String sql, Object[] params) {
        return jdbc.update(sql, params);
    }
}
